Análise RFM para Decisões de Negócio

Luciano Magalhães Luciano Magalhães   |   schedule Agosto, 2024  |   view_object_track Ciência de Dados


A análise RFM (Recência, Frequência e Valor Monetário) é uma ferramenta simples, mas eficaz, para segmentar clientes com base no histórico de compras. Ela é amplamente utilizada em campanhas de marketing para identificar quais clientes estão mais engajados e quais têm maior potencial de gerar receita.


Recência (R)

A recência refere-se ao tempo desde a última compra do cliente. Clientes que compraram recentemente são mais propensos a continuar interagindo com a marca. A recência pode/deve ser customizada de acordo com o segmento de negócio.

Frequência (F)

A frequência mede quantas compras foram feitas em um determinado período. Isso ajuda a identificar os clientes mais fiéis.

Valor Monetário (M)

O valor monetário no modelo RFM representa o parâmetro que gera valor para a empresa, e isso pode variar conforme o tipo de negócio.

Dessa forma, a análise RFM permite uma segmentação mais precisa dos clientes, o que facilita a criação de estratégias de marketing mais eficazes, personalizadas, e que agrega valor no negócio.

In [1]:
# suprimir avisos (warnings)  e criar função para ser aplicada nos gráficos

import warnings
warnings.filterwarnings("ignore")

#1. Função para aplicar estilo aos gráficos
from IPython.display import display, HTML
def estilo_grafico():
    sns.set_style('whitegrid')
    plt.rcParams.update({
        'axes.spines.top': False,         
        'axes.spines.right': False,       
        'axes.spines.left': True,        
        'axes.spines.bottom': True,       
        'axes.edgecolor': 'black',        
        'axes.facecolor': 'white',        
         'grid.color': 'gray',
        'grid.linestyle': '--',
        'grid.alpha': 0.7,
        'grid.linewidth': 0.7,
        'figure.facecolor': 'white',
        'figure.edgecolor': 'white',
        'savefig.facecolor': 'white',
        'savefig.edgecolor': 'white'
    })
    display(HTML("<style>.jp-OutputArea-output { display: flex; justify-content: center; }</style>"))

Análise RFM usando Python


Carregando o Dataset e apresentando os primeiros registros do dataset

In [2]:
import pandas as pd
import numpy as np

# carregar o dataset e apresentar os primeiros registros de dados
df_transacoes = pd.read_csv('transacoes_clientes.csv')

df_transacoes.head()
Out[2]:
cliente_id data_compra valor_compra
0 cliente_82 2023-12-30 17:41:40.000000 226.84
1 cliente_290 2024-07-06 17:20:24.543626 319.40
2 cliente_99 2024-08-25 17:20:24.543626 94.12
3 cliente_88 2023-10-12 17:20:24.543626 689.68
4 cliente_67 2024-04-14 21:56:49.000000 236.31
In [3]:
from datetime import datetime, timedelta

# Simulando datas de compra (nos últimos 365 dias)
data_compra = [datetime.today() - timedelta(days=np.random.randint(1, 365)) for _ in range(300)]

# Simulando valores de compra
valor_compra = np.random.uniform(55, 4370, 240)

Converção da coluna data_compra para o formato datetime e definição da data de hoje

In [4]:
# Converter a coluna 'data_compra' para o formato datetime
df_transacoes['data_compra'] = pd.to_datetime(df_transacoes['data_compra'])

# definir a data de hoje
hoje = datetime.today()

Calcular as três métricas do modelo RFM: recência, frequência e valor monetário.


1. Cálculo da Recência (R)

In [5]:
# calculando Recência
recencia = df_transacoes.groupby('cliente_id')['data_compra'].max().reset_index()
recencia['recencia'] = (hoje - recencia['data_compra']).dt.days

Explicação:

Aqui, o cálculo da recência é feito agrupando os dados pelo identificador do cliente (cliente_id). Para cada cliente, buscamos a data mais recente de compra usando max() na coluna data_compra. Em seguida, a métrica de recência é calculada subtraindo essa data de compra mais recente da data de referência (variável hoje, que representa o dia atual). O valor final da recência é expresso em número de dias.

Objetivo: A recência nos informa há quantos dias o cliente fez sua última compra. Quanto menor esse número, mais recente foi a interação do cliente com a empresa, sugerindo um cliente potencialmente mais engajado.


2. Cálculo da Frequência (F)

In [6]:
# calculando a Frequência
frequencia = df_transacoes.groupby('cliente_id')['cliente_id'].count().reset_index(name='frequencia')

Explicação:

Para calcular a frequência, agrupamos novamente os dados pelo identificador do cliente (cliente_id) e, em seguida, contamos o número de ocorrências de cliente_id em cada grupo. Isso nos dá a quantidade de vezes que cada cliente realizou uma compra no período de análise.

Objetivo: A frequência indica quantas vezes o cliente interagiu com o negócio ao longo do tempo. Clientes com alta frequência demonstram um nível maior de lealdade e engajamento com a empresa.


3. Cálculo do Valor Monetário (M)

In [7]:
# calculando valor monetário
valor_monetario = df_transacoes.groupby('cliente_id')['valor_compra'].sum().reset_index(name='valor_monetario')

Explicação:

A métrica de valor monetário é obtida somando o valor total das compras de cada cliente. Para isso, agrupamos os dados por cliente_id e aplicamos a função sum() na coluna valor_compra. Isso nos dá o valor total gasto por cada cliente durante o período analisado.

Objetivo: O valor monetário mede a quantidade de receita gerada por cada cliente. Clientes com um valor monetário alto representam uma parte significativa da receita da empresa e, portanto, são considerados clientes valiosos.


4. Combinação das Métricas RFM

In [8]:
# Combinar as métricas RFM em um único dataframe
df_rfm = recencia.merge(frequencia, on='cliente_id').merge(valor_monetario, on='cliente_id')

df_rfm.head()  # Exibir as primeiras linhas do dataframe
Out[8]:
cliente_id data_compra recencia frequencia valor_monetario
0 cliente_1 2024-08-01 17:20:24.545673 29 7 1854.80
1 cliente_10 2024-08-25 17:20:24.545673 5 3 883.44
2 cliente_100 2024-03-06 17:20:24.544623 177 4 996.93
3 cliente_101 2023-11-02 17:20:24.546681 302 2 507.78
4 cliente_102 2024-03-16 17:20:24.543626 167 5 1141.27

Explicação:

Após calcular individualmente as métricas de recência, frequência e valor monetário, combinamos esses três dataframes em um único dataframe chamado df_rfm. O método merge() é usado para fazer a junção dos dataframes com base no cliente_id.

Objetivo: A junção das métricas RFM em um único dataframe facilita a análise dos clientes, permitindo que as três dimensões sejam consideradas simultaneamente para tomar decisões estratégicas baseadas no comportamento do cliente.



Distribuição das Métricas RFM

Antes de realizar a segmentação, é importante visualizar como as métricas estão distribuídas entre os clientes. Isso nos ajudará a identificar padrões ou outliers que possam influenciar nossas estratégias.


Visualização da Distribuição da Recência

A distribuição da recência pode nos ajudar a identificar quantos clientes fizeram compras recentemente e quantos estão há mais tempo sem interagir com o negócio.

In [9]:
import matplotlib.pyplot as plt
import seaborn as sns
estilo_grafico()

# Plotar a distribuição da recência
plt.figure(figsize=(10, 6))
sns.histplot(df_rfm['recencia'], kde=False, bins=20, color='skyblue')
plt.title('Distribuição da Recência', fontsize=16, pad=20)
plt.xlabel('Número de Dias desde a última compra', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)
plt.show()
No description has been provided for this image

Explicação

Este gráfico de histograma mostra a distribuição da recência entre os clientes. Ele nos ajuda a entender quantos clientes fizeram compras recentemente em comparação com aqueles que não interagem há mais tempo. O conhecimento dessa distribuição é útil para segmentar diversos tipos de campanhas, como exemplo campanhas de reativação..



Visualização da Distribuição da Frequência

Agora, vamos analisar a frequência de compra, o que nos permite entender quantos clientes compram regularmente em comparação com aqueles que compram esporadicamente.

In [10]:
estilo_grafico()

# Calculando a tabela de frequência
tabela_frequencia = df_rfm['frequencia'].value_counts().sort_index()

# Supondo que 'tabela_frequencia' seja o dataframe contendo a frequência calculada
plt.figure(figsize=(10, 6))
tabela_frequencia.plot(kind='bar', color='lightcoral')
plt.title('Distribuição da Frequência', fontsize=16, pad=20)
plt.xlabel('Número de Compras', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)

# Ajuste para que os números fiquem na orientação normal
plt.xticks(rotation=0)

plt.show()
No description has been provided for this image

Explicação

Este gráfico de frequência é fundamental para identificar clientes que compram com maior regularidade, indicando maior lealdade ao negócio. Além disso, ele permite detectar clientes que estão comprando menos frequentemente, sugerindo a necessidade de campanhas de reativação para evitar que se distanciem da empresa.



Visualização da Distribuição do Valor Monetário

O valor monetário reflete quanto cada cliente gastou no total. Visualizar essa métrica nos ajuda a identificar os clientes mais valiosos.

In [11]:
estilo_grafico()
# Plotar a distribuição do valor monetário
plt.figure(figsize=(10, 6))
sns.histplot(df_rfm['valor_monetario'], kde=False, bins=30, color='lightgreen')
plt.title('Distribuição do Valor Monetário', fontsize=16, pad=20)
plt.xlabel('Valor Gasto (unidades monetárias)', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)
plt.show()
No description has been provided for this image

Explicação

Este gráfico nos dá uma ideia clara de como os valores de gasto estão distribuídos. Clientes que gastam mais podem ser alvo de campanhas premium, enquanto aqueles que gastam menos podem ser incentivados com ofertas especiais.


Calculando as Pontuações RFM


Após calcular as métricas individuais de Recência, Frequência e Valor Monetário, o próximo passo é atribuir pontuações a cada métrica para poder classificar os clientes. As pontuações RFM geralmente variam de 1 a 5, onde 1 indica menor prioridade e 5 maior prioridade. Neste bloco, utilizamos o método qcut para segmentar os clientes em quintis e atribuir essas pontuações de forma consistente.

In [12]:
# Calculando as Pontuações RFM ajustadas
df_rfm['pontuacao_R'] = pd.qcut(df_rfm['recencia'], 5, labels=range(5, 0, -1)).astype(int)
df_rfm['pontuacao_F'] = pd.qcut(df_rfm['frequencia'], 5, labels=range(1, 6)).astype(int)
df_rfm['pontuacao_M'] = pd.qcut(df_rfm['valor_monetario'], 5, labels=range(1, 6)).astype(int)

# Somando as pontuações para gerar a pontuação RFM final
# df_rfm['pontuacao_rfm'] = df_rfm['pontuacao_R'] + df_rfm['pontuacao_F'] + df_rfm['pontuacao_M']

# Concatenando as pontuações R, F, e M
df_rfm['pontuacao_rfm'] = df_rfm['pontuacao_R'].astype(str) + df_rfm['pontuacao_F'].astype(str) + df_rfm['pontuacao_M'].astype(str)


# Exibindo as primeiras linhas com as pontuações RFM
df_rfm.head()
Out[12]:
cliente_id data_compra recencia frequencia valor_monetario pontuacao_R pontuacao_F pontuacao_M pontuacao_rfm
0 cliente_1 2024-08-01 17:20:24.545673 29 7 1854.80 4 5 5 455
1 cliente_10 2024-08-25 17:20:24.545673 5 3 883.44 5 1 2 512
2 cliente_100 2024-03-06 17:20:24.544623 177 4 996.93 1 2 3 123
3 cliente_101 2023-11-02 17:20:24.546681 302 2 507.78 1 1 1 111
4 cliente_102 2024-03-16 17:20:24.543626 167 5 1141.27 2 3 3 233

Explicação

Neste bloco, foram calculadas as pontuações RFM para cada cliente com base nas três métricas. As pontuações foram atribuídas de forma que clientes com melhores desempenhos em Recência, Frequência e Valor Monetário recebem valores mais altos. A pontuação RFM total é a soma das três pontuações individuais, o que permite uma visão mais abrangente do comportamento de cada cliente.



Segmentação dos Clientes com Base nas pontuações RFM

Para finalizar, vamos segmentar os clientes com base nas pontuações RFM calculadas. Abaixo, categorizamos os clientes em grupos específicos, permitindo uma análise mais direcionada.

In [13]:
# Definindo faixas de pontuação para cada categoria de clientes
def classificar_cliente(rfm):
    if rfm['pontuacao_rfm'] in ['555', '554', '545', '544', '543', '454', '455']:
        return 'Campeões'
    elif rfm['pontuacao_rfm'] in [
        '543', '444', '435', '355', '354', '345', '344', '335',
        '353', '252', '543', '541', '542', '533', '532']:
        return 'Clientes Leal'
    elif rfm['pontuacao_rfm'].startswith(('553', '551', '552', '541', '542', '533', '532')):
        return 'Potencialmente Leais'
    elif rfm['pontuacao_rfm'] in [
        '512', '511', '422', '421', '412', '411', '311']:
        return 'Novos Clientes'
    elif rfm['pontuacao_rfm'] in [
        '525', '524', '523', '522', '521', '515', '514', '513', '425', '424', '413', '414', '415']:
        return 'Promissor'
    elif rfm['pontuacao_rfm'] in [
        '535', '534', '443', '434', '343', '334', '325', '324']:
        return 'Precisa de Atenção'
    elif rfm['pontuacao_rfm'] in [
        '155', '154', '144', '214', '215', '115', '114', '113']:
        return 'Não Pode Perdê-los'
    elif rfm['pontuacao_rfm'] in [
        '331', '321', '312', '221', '213']:
        return 'Prestes a Dormir'
    elif rfm['pontuacao_rfm'] in [
        '255', '254', '245', '244', '253', '252', '243', '242', '235', '234', '225', '224', '153', 
        '152', '145', '143', '142', '135', '134', '133', '125', '124']:
        return 'Em Risco'
    elif rfm['pontuacao_rfm'] in [
        '332', '322', '231', '241', '251', '233', '232', '223', '222', '132', '123', '122', '212', '211']:
        return 'Hibernando'
    elif rfm['pontuacao_rfm'] in ['111', '112', '121', '131', '141', '151']:
        return 'Perdido'
    else:
        return 'Cliente Regular'

# Aplicando a classificação ao dataframe de pontuações RFM
df_rfm['segmento_cliente'] = df_rfm.apply(classificar_cliente, axis=1)

# Exibindo as primeiras linhas do dataframe com as classificações
df_rfm.head()
Out[13]:
cliente_id data_compra recencia frequencia valor_monetario pontuacao_R pontuacao_F pontuacao_M pontuacao_rfm segmento_cliente
0 cliente_1 2024-08-01 17:20:24.545673 29 7 1854.80 4 5 5 455 Campeões
1 cliente_10 2024-08-25 17:20:24.545673 5 3 883.44 5 1 2 512 Novos Clientes
2 cliente_100 2024-03-06 17:20:24.544623 177 4 996.93 1 2 3 123 Hibernando
3 cliente_101 2023-11-02 17:20:24.546681 302 2 507.78 1 1 1 111 Perdido
4 cliente_102 2024-03-16 17:20:24.543626 167 5 1141.27 2 3 3 233 Hibernando

Explicação

Essa segmentação nos permite categorizar os clientes com base em seus scores RFM. Por exemplo, clientes VIP têm altas pontuações em todas as três métricas, enquanto os clientes a serem recuperados têm pontuações baixas em recência e frequência. Essas informações podem ser usadas para personalizar campanhas e estratégias de marketing.



Gráfico com Comparação das Pontuações

Agora, vamos apresentar no gráfico abaixo a comparação das pontuações médias de Recência, Frequência e Valor Monetário para cada segmento de clientes, permitindo uma análise das características de cada grupo.

In [14]:
import plotly.graph_objs as go
import plotly.colors
estilo_grafico()

# Definindo as cores pastéis
pastel_colors = plotly.colors.qualitative.Pastel
plt.figure(figsize=(16, 10))

# Calculando a média das pontuações de Recência, Frequência e Valor Monetário para cada segmento
pontuacoes_segmentos = df_rfm.groupby('segmento_cliente')[['pontuacao_R', 'pontuacao_F', 'pontuacao_M']].mean().reset_index()

# Criando o gráfico de barras agrupadas para comparar as pontuações
fig = go.Figure()

# Adicionando as barras para a pontuação de Recência
fig.add_trace(go.Bar(
    x=pontuacoes_segmentos['segmento_cliente'],
    y=pontuacoes_segmentos['pontuacao_R'],
    name='Pontuação de Recência',
    marker_color=pastel_colors[0]  # Cor pastel
))

# Adicionando as barras para a pontuação de Frequência
fig.add_trace(go.Bar(
    x=pontuacoes_segmentos['segmento_cliente'],
    y=pontuacoes_segmentos['pontuacao_F'],
    name='Pontuação de Frequência',
    marker_color=pastel_colors[1]  # Cor pastel
))

# Adicionando as barras para a pontuação de Valor Monetário
fig.add_trace(go.Bar(
    x=pontuacoes_segmentos['segmento_cliente'],
    y=pontuacoes_segmentos['pontuacao_M'],
    name='Pontuação de Valor Monetário',
    marker_color=pastel_colors[2]  # Cor pastel
))

# Atualizando o layout do gráfico
fig.update_layout(
    title='Comparação das Pontuações de Recência, Frequência e Valor Monetário por Segmento',
    xaxis_title='Segmentos de Clientes RFM',
    yaxis_title='Pontuação',
    barmode='group',
    showlegend=True,
    plot_bgcolor='rgba(0,0,0,0)'  # Remover cor de fundo
)

# Exibindo o gráfico
fig.show()
<Figure size 1600x1000 with 0 Axes>


Gráfico de Comparação dos Segmentos

Agora, vamor olhar a distribuição dos clientes em diferentes segmentos RFM, como Campeões, Clientes Leais e outros, permitindo uma visão clara da quantidade de clientes em cada categoria.

In [23]:
# Chama a função estilo_grafico para aplicar o estilo estabelecido
estilo_grafico()

# Contando a quantidade de clientes em cada segmento
contagem_segmentos = df_rfm['segmento_cliente'].value_counts()

# Calculando o total de clientes
total_clientes = contagem_segmentos.sum()

# Calculando os percentuais corretos (em relação ao total de clientes)
percentuais = (contagem_segmentos / total_clientes) * 100
# Criando o gráfico com Matplotlib/Seaborn
plt.figure(figsize=(13, 6))
ax = sns.barplot(x=contagem_segmentos.index, y=contagem_segmentos.values, palette='pastel')

# Adicionando os totais e percentuais corretos
for i, (valor, percentual) in enumerate(zip(contagem_segmentos, percentuais)):
    ax.text(i, valor - (valor * 0.2), f'{percentual:.1f}%', ha='center', va='bottom', fontsize=15, color='black')  # Percentual dentro da barra

# Ajustando os títulos e rótulos dos eixos
plt.title('Comparação dos Segmentos de Clientes RFM', fontsize=16, pad=20)
plt.xlabel('Segmentos de Clientes RFM', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)

# Rotacionando os rótulos do eixo X para evitar sobreposição
plt.xticks(rotation=45, ha='right')

# Exibindo o gráfico
plt.show()
No description has been provided for this image

Explicação

Esse gráfico pode nos auxiliar na identificação de quais segmentos possuem maior quantidade de clientes, oferecendo insights para estratégias de marketing específicas.



Gráfico de Dispersão (Scatter Plot)

Vamos agora apresentar gráficos de dispersão que mostram a relação entre duas variáveis, como recência e valor monetário ou frequência e valor monetário. Eles irão ajudar a identificar correlações e padrões que não são visíveis apenas nas distribuições individuais.

In [17]:
estilo_grafico()
# Gráficos de dispersão para as métricas RFM
plt.figure(figsize=(15, 5))

# Dispersão de Recência vs Valor Monetário
plt.subplot(1, 2, 1)
sns.scatterplot(x='recencia', y='valor_monetario', data=df_rfm, palette='pastel')
plt.title('Recência vs Valor Monetário', fontsize=16, pad=20)
plt.xlabel('Recência (dias)', fontsize=16, labelpad=20)
plt.ylabel('Valor Monetário (total)', fontsize=16, labelpad=20)

# Dispersão de Frequência vs Valor Monetário
plt.subplot(1, 2, 2)
sns.scatterplot(x='frequencia', y='valor_monetario', data=df_rfm, palette='pastel')
plt.title('Frequência vs Valor Monetário', fontsize=16, pad=20)
plt.xlabel('Frequência (compras)', fontsize=16, labelpad=20)
plt.ylabel('Valor Monetário (total)', fontsize=16, labelpad=20)

plt.tight_layout()
plt.show()
No description has been provided for this image

Explicação

Nesses gráficos de dispersão comparamos a recência e a frequência de compras em relação ao valor monetário total, proporcionando uma visão clara das interações entre essas variáveis. No primeiro gráfico notamos como clientes com recência menor tendem a gerar maiores valores monetários. Isso pode indicar que clientes que compraram recentemente ainda estão engajados e gerando mais receita. No segundo gráfico, observamos uma correlação positiva, ou seja, conforme a frequência de compras aumenta, o valor monetário total também tende a crescer, sugerindo que clientes recorrentes geralmente gastam mais.

Esses gráficos ajudam a identificar padrões que podem direcionar estratégias, como focar em clientes com alta frequência para programas de fidelização ou monitorar aqueles com baixa recência, mas alto valor, para reativação.



Gráficos de Calor (Heatmaps)

Em seguida, vamos analisar a correlação entre as três métricas principais do modelo RFM utilizando um gráfico de calor (heatmap).

In [18]:
estilo_grafico()
# Gráfico de Calor (Heatmap) para as correlações entre as métricas RFM
plt.figure(figsize=(10, 6))
correlacao = df_rfm[['recencia', 'frequencia', 'valor_monetario']].corr()

# Plotando o heatmap
sns.heatmap(correlacao, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Correlação entre Métricas RFM', fontsize=16, pad=20)

plt.show()
No description has been provided for this image

Explicação

O heatmap nos mostra uma correlação positiva forte entre Frequência e Valor Monetário, sugerindo que clientes que compram com mais frequência tendem a gastar mais. Esse insight é valioso para estratégias que buscam aumentar o valor de cada cliente por meio de compras mais frequentes.



Conclusão

A análise RFM é uma estratégia eficaz para segmentar clientes, utilizando três métricas principais: recência, frequência e valor monetário. Essa abordagem ajuda categorizar os clientes com base em seu comportamento, ajustar as estratégias da empresa para melhorar o relacionamento com eles, e gerar valor no negócio. Além disso, os gráficos dessas métricas fornecem insights visuais importantes sobre a interação dos clientes com o negócio.

Espero que tenham gostado deste artigo sobre Análise RFM usando Python.


© Copyright 2024 | Luciano Magalhães
In [ ]: